# coding:utf-8
import asyncio
import logging

from functools import partial
from aiobsonrpc import JSONRpc

__license__ = 'http://mozilla.org/MPL/2.0/'


class Base:

    def __init__(self, ip, port, loop=None, services=None, **options):
        self._ip = ip
        self._port = port
        self._loop = loop
        self._services = services
        self._options = options


class CreateServer(Base):
    """
    创建 socket 服务端
    """

    def __init__(self, ip, port, loop=None, services=None, **options):
        super(CreateServer, self).__init__(ip, port, loop, services, **options)

    def _on_connect(self):
        return partial(JSONRpc, loop=self._loop, services=self._services, **self._options)

    async def _cancel(self, task):
        task.cancel()
        await task
        print(f"Task done : {task.done()}")
        print(f"Task cancelled : {task.cancelled()}", )

    def run(self):
        self.loop = asyncio.get_event_loop()
        server = asyncio.start_server(self._on_connect(),
                                      self._ip,
                                      self._port,
                                      loop=self.loop)
        task = self.loop.create_task(server)
        try:
            self.loop.run_forever()
        except KeyboardInterrupt as e:
            logging.error(f"{e}")
            asyncio.run(self._cancel(task))
        finally:
            self.loop.close()


class ClientConnect(Base):
    """
    客户端连接
    """

    def __init__(self, ip, port, loop=None, services=None, **options):
        super(ClientConnect, self).__init__(ip, port, loop, services, **options)
        self.reader = None
        self.writer = None
        self.rpc = None

    async def _on_connect(self):
        self.reader, self.writer = await asyncio.open_connection(self._ip,
                                                                 self._port)

    def _get_rpc(self):
        self.rpc = JSONRpc(self.reader, self.writer, loop=self._loop, services=self._services, **self._options)

    async def run(self):
        await self._on_connect()
        self._get_rpc()
